package com.hexiang.handler;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.rpc.RpcException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * Let Spring handle the exception, we just override the status code
     *
     * @param response
     * @throws IOException
     */
    @ExceptionHandler(BlockException.class)
    public void sentinelException(BlockException e, HttpServletResponse response) throws IOException {
        String msg = "";
        int code = 0;
        if (e instanceof FlowException) {
            msg = "接口被限流";
            code = 1;
        } else if (e instanceof BlockException) {
            msg = "接口被降级";
            code = 2;
        } else if (e instanceof SystemBlockException) {
            msg = "系统繁忙";
            code = 3;
        }
        log.error("sentinelException:{}", msg);
        response.sendError(code);
    }

    @ExceptionHandler(RemotingException.class)
    public void remotingException(RemotingException remotingException, HttpServletResponse response) throws IOException {
        String msg = "";
        int code = 0;
        if (remotingException.getCause() instanceof SentinelRpcException) {
            SentinelRpcException sentinelRpcException = (SentinelRpcException) remotingException.getCause();
            if (sentinelRpcException.getCause() instanceof FlowException) {
                msg = "接口被限流";
                code = 1;
            }
        }
        log.error("remotingException:{}", msg);
        response.sendError(code);
    }

    @ExceptionHandler(Exception.class)
    public void internalServerError(Exception exception, HttpServletResponse response) throws IOException {
        log.error("internalServerError:{}", exception);
        response.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value());
    }

    @ExceptionHandler(RpcException.class)
    public void rpcException(RpcException exception, HttpServletResponse response) throws IOException {
        log.error("rpcException:{}", exception);
        response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value());
    }

}
